import User, { UserSchema } from '../model/users'
import * as mongoose from 'mongoose'
import { Context } from 'Koa'
import { get, post, patch, Methods, controller, remove, put } from '../decorator'
import * as jsonwebtoken from 'jsonwebtoken'
import config from '../config'
import { use } from '../decorator/use'
import auth from '../middleware/auth'
import checkOwner from '../middleware/checkOwner'
import checkUserExist from '../middleware/checkUserExist'
import checkTopicExist from '../middleware/checkTopicExist'
@controller('/users')
export class UsersController {
  @post('/')
  async create(ctx: Context) {
    ctx.verifyParams?.({
      name: { type: 'string', required: true },
      password: { type: 'string', required: true },
    })

    const { name } = ctx.request.body
    const repeatedUser = await User.findOne({ name })
    if (repeatedUser) {
      ctx.throw(409, '用户已经占用')
    }
    const user = await new User(ctx.request.body).save()
    ctx.body = user
  }

  @patch('/:id')
  @use(checkOwner)
  @use(auth)
  async update(ctx: Context) {
    ctx.verifyParams?.({
      name: { type: 'string', required: false },
      password: { type: 'string', required: false },
      avatar_url: { type: 'string', required: false },
      description: { type: 'string', required: false },
      business: { type: 'string', required: false },
      employments: { type: 'string', required: false },
      homepage: { type: 'string', required: false },
    })
    const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
    if (!user) {
      ctx.throw(404, '用户不存在')
    }
    ctx.body = user
  }

  @remove('/:id')
  @use(checkOwner)
  @use(auth)
  async delete(ctx: Context) {
    const user = await User.findByIdAndRemove(ctx.params.id)
    if (!user) {
      ctx.throw(404, '用户不存在')
    }
    ctx.status = 204
  }

  @get('/')
  async find(ctx: Context) {
    const { per_page = 10 } = ctx.query
    const page = Math.max(ctx.query.page * 1, 1) - 1
    const perPage = Math.max(per_page * 1, 1)
    ctx.body = await User.find({ name: new RegExp(ctx.query.q) })
      .limit(perPage)
      .skip(page * perPage)
  }

  @get('/:id')
  async findById(ctx: Context) {
    const { fields = '' } = ctx.query
    const selectFields = fields
      .split(';')
      .filter((f: string) => f)
      .map((f: string) => ' +' + f)
      .join('')
    const user = await User.findById(ctx.params.id).select(selectFields)
    if (!user) {
      ctx.throw(404, '用户不存在')
    }
    ctx.body = user
  }

  @post('/login')
  async login(ctx: Context) {
    ctx.verifyParams?.({
      name: { type: 'string', required: true },
      password: { type: 'string', required: true },
    })
    const user = (await User.findOne(ctx.request.body)) as UserSchema
    if (!user) {
      ctx.throw(401, '用户名或密码不正确')
    }
    const { _id, name } = user
    const token = jsonwebtoken.sign({ _id, name }, config.secret, {
      expiresIn: '1d',
    })
    ctx.body = { token }
  }

  @put('/following/:id')
  @use(checkUserExist)
  @use(auth)
  async follow(ctx: Context) {
    const me = await User.findById(ctx.state.user._id).select('+following')
    // const index = me?.following.map((id:mongoose.Types.ObjectId) => id.toString()).indexOf(ctx.params.id)
    if (
      !me?.following
        ?.map((id: mongoose.Types.ObjectId) => id.toString())
        .includes(ctx.params.id)
    ) {
      me?.following?.push(ctx.params.id)
      me?.save()
    }
    ctx.status = 204
  }

  @remove('/following/:id')
  @use(checkUserExist)
  @use(auth)
  async unfollow(ctx: Context) {
    const me = await User.findById(ctx.state.user._id).select('+following')
    const index = me?.following
      ?.map((id: mongoose.Types.ObjectId) => id.toString())
      .indexOf(ctx.params.id)
    if (index! > -1) {
      me?.following?.splice(index!, 1)
      me?.save()
    }
    ctx.status = 204
  }

  @get('/:id/following')
  async listFollowing(ctx: Context) {
    const user = await User.findById(ctx.params.id)
      .select('+following')
      .populate('following')
    if (!user) {
      ctx.throw(404, '用户不存在')
    }
    ctx.body = user.following
  }

  @get('/:id/followers')
  async listFollowers(ctx: Context) {
    const users = await User.find({ following: ctx.params.id })
    ctx.body = users
  }

  @put('/followingTopics/:id')
  @use(checkTopicExist)
  @use(auth)
  async followTopic(ctx: Context) {
    const me = await User.findById(ctx.state.user._id).select(
      '+followingTopics'
    )
    if (
      !me?.followingTopics?.map((id) => id.toString()).includes(ctx.params.id)
    ) {
      me?.followingTopics?.push(ctx.params.id)
      me?.save()
    }
    ctx.status = 204
  }

  @remove('/followingTopics/:id')
  @use(checkTopicExist)
  @use(auth)
  async unfollowTopic(ctx: Context) {
    const me = await User.findById(ctx.state.user._id).select('+followingTopics');
    const index = me?.followingTopics?.map(id => id.toString()).indexOf(ctx.params.id);
    if (index! > -1) {
      me?.followingTopics?.splice(index!, 1);
      me?.save();
    }
    ctx.status = 204;
  }

  @get('/:id/followingTopics')
  async listFollowingTopics(ctx:Context) {
    const user = await User.findById(ctx.params.id).select('+followingTopics').populate('followingTopics');
    if (!user) { ctx.throw(404, '用户不存在'); }
    ctx.body = user.followingTopics;
  }
}
